﻿using System;
using System.Diagnostics.Tracing;
using System.Threading;

namespace Sustainalytics.Admin.CRMSynchronization.Utility
{
    [EventSource(Name = "Sustainalytics-ClientPlatform-CrmSynchronization")]
    public sealed class CrmSyncEventSource : EventSource
    {
        private static Lazy<CrmSyncEventSource> _lazyLog = new Lazy<CrmSyncEventSource>(InitLog, LazyThreadSafetyMode.ExecutionAndPublication);

        public static CrmSyncEventSource Log => _lazyLog.Value;

        [NonEvent]
        private static CrmSyncEventSource InitLog()
        {
            var log = new CrmSyncEventSource();
            log.Ping();

            return log;
        }

        [Event(1, Level = EventLevel.LogAlways, Message = "Ping")]
        public void Ping()
        {
            if (IsEnabled())
                WriteEvent(1);
        }

        #region Users

        [Event(101, Task = Tasks.UsersSync, Opcode = EventOpcode.Start, Level = EventLevel.Informational, Message = "Sync/Users/Start")]
        public void UsersSyncStart(DateTime syncDate)
        {
            if (IsEnabled())
                WriteEvent(101, syncDate);
        }

        [Event(102, Task = Tasks.UsersSync, Opcode = EventOpcode.Stop, Level = EventLevel.Informational, Message = "Sync/Users/Stop")]
        public void UsersSyncStop(DateTime syncDate)
        {
            if (IsEnabled())
                WriteEvent(102, syncDate);
        }

        [Event(103, Level = EventLevel.Error, Message = "Sync/Users/Failed")]
        public void UsersSyncFailed(DateTime syncDate, string exceptionType, string exceptionMessage, string exceptionInformation)
        {
            if (IsEnabled())
                WriteEvent(103, syncDate, exceptionType, exceptionMessage, exceptionInformation);
        }

        [Event(104, Level = EventLevel.Informational, Message = "Sync/Users/Succeded")]
        public void UsersSyncSucceeded(DateTime syncDate, int created, int deleted, int updated)
        {
            if (IsEnabled())
                WriteEvent(104, syncDate, created, deleted, updated);
        }

        [NonEvent]
        public void UserSync(DateTime syncDate, string step, UsersSynchronization.SyncResult result)
        {
            UserSync(syncDate, step, result.Created, result.Deleted, result.Updated);
        }

        [Event(105, Level = EventLevel.Informational, Message = "Sync/Users/Progress")]
        public void UserSync(DateTime syncDate, string step, int created, int deleted, int updated)
        {
            if (IsEnabled())
                WriteEvent(105, syncDate, step, created, deleted, updated);
        }

        [NonEvent]
        public void UserSyncSave(DateTime syncDate, Entities.User user)
        {
            UserSyncSave(syncDate, user.Id, user.Email, user.Status.ToString(),
                user.AccountId == null ? "" : user.AccountId.ToString(),
                user.Sync_AccountStatus.ToString());
        }

        [Event(106, Level = EventLevel.Verbose, Message = "Sync/Users/Save")]
        public void UserSyncSave(DateTime syncDate, System.Guid id, string email, string status, string accountId, string accountStatus)
        {
            if (IsEnabled(EventLevel.Verbose, EventKeywords.All))
                WriteEvent(106, syncDate, id, email, status, accountId, accountStatus);
        }

        [Event(107, Level = EventLevel.Verbose, Message = "Sync/Users/NullEmail")]
        public void UserNullEmail(DateTime syncDate, System.Guid id, string firstName, string middleName, string lastName, string accountId, string accountStatus)
        {
            if (IsEnabled(EventLevel.Verbose, EventKeywords.All))
                WriteEvent(107, syncDate, id, firstName, middleName, lastName, accountId, accountStatus);
        }

        [Event(108, Level = EventLevel.Verbose, Message = "Sync/Users/DuplicateEmail")]
        public void UserDuplicateEmail(DateTime syncDate, System.Guid id, string email, string firstName, string lastName, string accountId, string accountStatus)
        {
            if (IsEnabled(EventLevel.Verbose, EventKeywords.All))
                WriteEvent(108, syncDate, id, email, firstName, lastName, accountId, accountStatus);
        }

        [Event(109, Level = EventLevel.Verbose, Message = "Sync/Users/ResetPasswordEmail")]
        public void ResetPasswordEmail(DateTime syncDate, System.Guid id, string email)
        {
            if (IsEnabled(EventLevel.Verbose, EventKeywords.All))
                WriteEvent(109, syncDate, id, email);
        }

        [Event(110, Level = EventLevel.Verbose, Message = "Sync/Users/StartProcessing")]
        public void StartProcessingContact(DateTime syncDate, System.Guid id, string email, string firstName, string lastEmail)
        {
            if (IsEnabled(EventLevel.Verbose, EventKeywords.All))
                WriteEvent(110, syncDate, id, email, firstName, lastEmail);
        }

        #endregion

        #region Accounts

        [Event(201, Task = Tasks.AccountsSync, Opcode = EventOpcode.Start, Level = EventLevel.Informational, Message = "Sync/Accounts/Start")]
        public void AccountsSyncStart(DateTime currentSyncDate)
        {
            if (IsEnabled())
                WriteEvent(201, currentSyncDate);
        }

        [Event(202, Task = Tasks.AccountsSync, Opcode = EventOpcode.Stop, Level = EventLevel.Informational, Message = "Sync/Accounts/Stop")]
        public void AccountsSyncStop(DateTime currentSyncDate)
        {
            if (IsEnabled())
                WriteEvent(202, currentSyncDate);
        }

        [Event(203, Level = EventLevel.Error, Message = "Sync/Accounts/Failed")]
        public void AccountsSyncFailed(DateTime syncDate, string exceptionType, string exceptionMessage, string exceptionInformation)
        {
            if (IsEnabled())
                WriteEvent(203, syncDate, exceptionMessage, exceptionInformation);
        }

        [Event(204, Level = EventLevel.Informational, Message = "Sync/Accounts/Succeded")]
        public void AccountsSyncSucceeded(DateTime syncDate, int created, int deleted, int updated)
        {
            if (IsEnabled())
                WriteEvent(204, syncDate, created, deleted, updated);
        }

        [Event(206, Level = EventLevel.Error, Message = "Sync/Accounts/NoDefaultProfileFound")]
        public void NoDefaultProfileFound(DateTime syncDate)
        {
            if (IsEnabled())
                WriteEvent(206, syncDate);
        }

        #endregion

        [Event(205, Level = EventLevel.Error, Message = "Sync/Failed")]
        public void SyncFailed(string exceptionType, string exceptionMessage, string exceptionInformation)
        {
            if (IsEnabled())
                WriteEvent(205, exceptionType, exceptionMessage, exceptionInformation);
        }

        #region Universes

        [Event(301, Task = Tasks.UniversesSync, Opcode = EventOpcode.Start, Level = EventLevel.Informational, Message = "Sync/Universes/Start")]
        public void UniversesSyncStart(DateTime currentSyncDate)
        {
            if (IsEnabled())
                WriteEvent(301, currentSyncDate);
        }

        [Event(302, Task = Tasks.UniversesSync, Opcode = EventOpcode.Stop, Level = EventLevel.Informational, Message = "Sync/Universes/Stop")]
        public void UniversesSyncStop(DateTime currentSyncDate)
        {
            if (IsEnabled())
                WriteEvent(302, currentSyncDate);
        }

        #endregion

        #region Claims

        [Event(401, Task = Tasks.ClaimsSync, Opcode = EventOpcode.Start, Level = EventLevel.Informational, Message = "Sync/Claims/Start")]
        public void ClaimsSyncStart(DateTime currentSyncDate)
        {
            if (IsEnabled())
                WriteEvent(401, currentSyncDate);
        }

        [Event(402, Task = Tasks.ClaimsSync, Opcode = EventOpcode.Stop, Level = EventLevel.Informational, Message = "Sync/Claims/Stop")]
        public void ClaimsSyncStop(DateTime currentSyncDate)
        {
            if (IsEnabled())
                WriteEvent(402, currentSyncDate);
        }

        [Event(403, Level = EventLevel.Error, Message = "Sync/Claims/Failed")]
        public void ClaimsSyncFailed(DateTime syncDate, string exceptionType, string exceptionMessage, string exceptionInformation)
        {
            if (IsEnabled())
                WriteEvent(403, syncDate, exceptionMessage, exceptionInformation);
        }

        [Event(404, Level = EventLevel.Informational, Message = "Sync/Claims/Succeded")]
        public void ClaimsSyncSucceeded(DateTime syncDate)
        {
            if (IsEnabled())
                WriteEvent(404, syncDate);
        }

        [Event(405, Level = EventLevel.Verbose, Message = "Sync/Claims/PermissionAdded")]
        internal void PermissionAdded(string permission, string claims)
        {
            if (IsEnabled())
                WriteEvent(405, permission, claims);
        }

        [Event(406, Level = EventLevel.Verbose, Message = "Sync/Claims/AccountAdded")]
        internal void AccountAdded(string account, string claims)
        {
            if (IsEnabled())
                WriteEvent(406, account, claims);
        }

        #endregion

        #region Keywords / Tasks / Opcodes

        public class Keywords   // This is a bitvector
        {
            public const EventKeywords Debug = (EventKeywords)0x0002;
        }

        public class Tasks
        {
            public const EventTask UsersSync = (EventTask)0x1;// > 0
            public const EventTask AccountsSync = (EventTask)0x2;// > 0
            public const EventTask UniversesSync = (EventTask)0x3; // > 0
            public const EventTask ClaimsSync = (EventTask)0x4; // > 0
        }

        #endregion
    }
}
